package OBS;

import Databasehandler.DBCommunicator;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;

/**
 * Objekt til håndtering af en Superbrugers funktioner i systemet. Arver også funktioner fra en almindelig bruger.
 *
 * @author Daniel Koch
 */
public class OBSSuperUser extends OBSUser {
    /**
     * Initialiserer DBC med et DBCommunicator-objekt.
     *
     * @param DBC
     */
    public OBSSuperUser(DBCommunicator DBC) {
        super(DBC);
    }

    /**
     * Konverterer en String til et GregorianCalendar-objekt.
     * 
     * @param date
     * @return Et GregorianCalendar-objekt
     */
    private GregorianCalendar stringToDate(String date) {
        GregorianCalendar gc = new GregorianCalendar();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            gc.setTime(format.parse(date));
            return gc;
        }
        catch(Exception e) {
            e.printStackTrace();
            return new GregorianCalendar();
        }
    }

    //<editor-fold desc="Kunde">

    /**
     * Opretter en kunde ud fra et Customer-objekt.
     *
     * @param customer
     */
    public void createCustomer(Customer customer) throws Exception {
        this.DBC.createCustomer(customer.getName());
    }

    /**
     * Redigérer en kunde ud fra et Customre-objekt.
     * 
     * @param customer
     */
    public void editCustomer(Customer customer) throws Exception {
        this.DBC.editCustomer(customer.getID(), customer.getName());
    }

    /**
     * Slet en kunde
     * @param customer
     */
    public void deleteCustomer(Customer customer) throws Exception {
        // Slet alle abonnenter
        OBSReportSubscriber[] OBSReportSubscribers = customer.getOBSReportSubscribers();
        for(int i = 0;i < OBSReportSubscribers.length;i++) {
            deleteOBSReportSubscriber(OBSReportSubscribers[i]);
        }

        // Slet alle batchrapportsystemer
        BatchReportSystem[] batchReportSystems = customer.getBatchReportSystems();
        for(int i = 0;i < batchReportSystems.length;i++) {
            deleteBatchReportSystem(batchReportSystems[i]);
        }
        this.DBC.deleteCustomer(customer.getID());
    }

    /**
     * Hent en kunde fra databasen ud fra customerID og konverterer det til et Customer-objekt.
     * 
     * @param customerID
     * @return Et Customer-objekt
     */
    public Customer getCustomer(int customerID) throws Exception {
        ResultSet rs = this.DBC.getCustomer(customerID);
        rs.next();
        int id = rs.getInt(1);
        String name = rs.getString(2);
        BatchReportSystem[] batchReportSystems = getCustomerBatchReportSystems(customerID);
        OBSReportSubscriber[] OBSReportSubscribers = getCustomerOBSReportSubscribers(customerID);
        return new Customer(id, name, batchReportSystems, OBSReportSubscribers);
    }

    /**
     * Henter alle kunder fra databasen og konverterer dem til Customer-objekter.
     * @return Et Array af Customer-objekter
     */
    public Customer[] getCustomers() throws Exception {
        ArrayList<Customer> al = new ArrayList<Customer>();
        ResultSet rs = this.DBC.getCustomers();
        while(rs.next()) {
            int id = rs.getInt(1);
            String name = rs.getString(2);
            BatchReportSystem[] batchReportSystems = getCustomerBatchReportSystems(id);
            OBSReportSubscriber[] OBSReportSubscribers = getCustomerOBSReportSubscribers(id);
            al.add(new Customer(id, name, batchReportSystems, OBSReportSubscribers));
        }
        Customer[] a = new Customer[al.size()];
        for(int i = 0;i < a.length;i++) {
            a[i] = al.get(i);
        }
        return a;
    }

    //</editor-fold>

    //<editor-fold desc="Batchrapportsystem">

    /**
     * Opret et batchrapportsystem
     * @param batchReportSystem
     * @param customer
     */
    public void createBatchReportSystem(BatchReportSystem batchReportSystem, Customer customer) throws Exception {
        this.DBC.createBatchReportSystem(batchReportSystem.getName(), batchReportSystem.getBatchReportInterval().getID(), customer.getID());
    }

    /**
     * Redigér et batchrapportsystem
     * @param batchReportSystem
     */
    public void editBatchReportSystem(BatchReportSystem batchReportSystem) {
        try {
            this.DBC.editBatchReportSystem(batchReportSystem.getID(), batchReportSystem.getName(), batchReportSystem.getBatchReportInterval().getID());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Slet et batchrapportsystem
     * @param batchReportSystem
     */
    public void deleteBatchReportSystem(BatchReportSystem batchReportSystem) {
        try {
            // Sletter alle batchrapporter
            BatchReport[] batchReports = batchReportSystem.getBatchReports();
            for(int i = 0;i < batchReports.length;i++) {
                deleteBatchReport(batchReports[i]);
            }
            this.DBC.deleteBatchReportSystem(batchReportSystem.getID());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Hent alle batchrapportsystemer
     * @return
     */
    public BatchReportSystem[] getBatchReportSystems() {
        try {
            ArrayList<BatchReportSystem> al = new ArrayList<BatchReportSystem>();
            ResultSet rs = this.DBC.getBatchReportSystems();
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                BatchReportInterval batchReportInterval = getBatchReportInterval(rs.getInt(3));
                Customer customer = getCustomer(rs.getInt(4));
                al.add(new BatchReportSystem(id, name, batchReportInterval, null));
            }
            BatchReportSystem[] a = new BatchReportSystem[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Hent alle batchrapportsystemer for en kunde
     * @param customerID
     * @return
     */
    public BatchReportSystem[] getCustomerBatchReportSystems(int customerID) {
        try {
            ArrayList<BatchReportSystem> al = new ArrayList<BatchReportSystem>();
            ResultSet rs = this.DBC.getCustomerBatchReportSystems(customerID);
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                BatchReportInterval batchReportInterval = getBatchReportInterval(rs.getInt(3));
                BatchReport[] batchReports = getBatchReportSystemBatchReports(id);
                BatchReport[] currentBatchReports = getCurrentBatchReportSystemBatchReports(id);
                al.add(new BatchReportSystem(id, name, batchReportInterval, batchReports, currentBatchReports));
            }
            BatchReportSystem[] a = new BatchReportSystem[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Hent aktuelle batchrapportsystemer
     * @return
     */
    public BatchReportSystem[] getCurrentBatchReportSystems() {
        try {
            ArrayList<BatchReportSystem> al = new ArrayList<BatchReportSystem>();
            ResultSet rs = this.DBC.getCurrentBatchReportSystems();
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                BatchReportInterval batchReportInterval = getBatchReportInterval(rs.getInt(3));
                BatchReport[] batchReports = getBatchReportSystemBatchReports(id);
                BatchReport[] currentBatchReports = getCurrentBatchReportSystemBatchReports(id);
                al.add(new BatchReportSystem(id, name, batchReportInterval, batchReports, currentBatchReports));
            }
            BatchReportSystem[] a = new BatchReportSystem[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //</editor-fold>

    //<editor-fold desc="Abonnent">

    /**
     * Opret en abonnent
     * @param OBSReportSubscriber
     * @param customer
     */
    public void createOBSReportSubscriber(OBSReportSubscriber OBSReportSubscriber, Customer customer) {
        try {
            this.DBC.createOBSReportSubscriber(OBSReportSubscriber.getName(), customer.getID(), OBSReportSubscriber.getEmail());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Redigér en abonnent
     * @param OBSReportSubscriber
     */
    public void editOBSReportSubscriber(OBSReportSubscriber OBSReportSubscriber) {
        try {
            this.DBC.editOBSReportSubscriber(OBSReportSubscriber.getID(), OBSReportSubscriber.getName(), OBSReportSubscriber.getEmail());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Slet en abonnent
     * @param OBSReportSubscriber
     */
    public void deleteOBSReportSubscriber(OBSReportSubscriber OBSReportSubscriber) {
        try {
            this.DBC.deleteOBSReportSubscription(OBSReportSubscriber.getID());
            this.DBC.deleteOBSReportSubscriber(OBSReportSubscriber.getID());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Hent en abonnent
     * @param OBSReportSubscriberID
     * @return
     */
    public OBSReportSubscriber getOBSReportSubscriber(int OBSReportSubscriberID) {
        try {
            ResultSet rs = this.DBC.getOBSReportSubscriber(OBSReportSubscriberID);
            if(rs.next()) {
                String name = rs.getString(3);
                String email = rs.getString(4);
                OBSReportSubscription OBSReportSubscription = getOBSReportSubscriberOBSReportSubscription(OBSReportSubscriberID);
                return new OBSReportSubscriber(OBSReportSubscriberID, name, email, OBSReportSubscription);
            }
            return null;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Hent alle batchrapportsystemer
     * @return
     */
    public OBSReportSubscriber[] getOBSReportSubscribers() {
        try {
            ArrayList<OBSReportSubscriber> al = new ArrayList<OBSReportSubscriber>();
            ResultSet rs = this.DBC.getOBSReportSubscribers();
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(3);
                String email = rs.getString(4);
                OBSReportSubscription OBSReportSubscription = getOBSReportSubscriberOBSReportSubscription(id);
                al.add(new OBSReportSubscriber(id, name, email, OBSReportSubscription));
            }
            OBSReportSubscriber[] a = new OBSReportSubscriber[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Hent alle batchrapportsystemer for en kunde
     * @param customerID
     * @return
     */
    public OBSReportSubscriber[] getCustomerOBSReportSubscribers(int customerID) {
        try {
            ArrayList<OBSReportSubscriber> al = new ArrayList<OBSReportSubscriber>();
            ResultSet rs = this.DBC.getCustomerOBSReportSubscribers(customerID);
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(3);
                String email = rs.getString(4);
                OBSReportSubscription OBSReportSubscription = getOBSReportSubscriberOBSReportSubscription(id);
                al.add(new OBSReportSubscriber(id, name, email, OBSReportSubscription));
            }
            OBSReportSubscriber[] a = new OBSReportSubscriber[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //</editor-fold>

    //<editor-fold desc="Abonnement">

    /**
     * Opdatér et abonnement
     * @param OBSReportSubscriber
     */
    public void editOBSReportSubscription(OBSReportSubscriber OBSReportSubscriber) {
        try {
            // Slet tidligere abonnementer
            this.DBC.deleteOBSReportSubscription(OBSReportSubscriber.getID());

            // Opret de nye abonnementer
            for(int i = 0;i < OBSReportSubscriber.getOBSReportSubscription().getBatchReportSystems().length;i++) {
                this.DBC.createOBSReportSubscription(OBSReportSubscriber.getOBSReportSubscription().getBatchReportSystems()[i].getID(), OBSReportSubscriber.getID());
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    //</editor-fold>

    //<editor-fold desc="Batchrapport">

    /**
     * Slet en batchrapport
     * @param batchReport
     */
    public void deleteBatchReport(BatchReport batchReport) {
        try {
            this.DBC.deleteBatchReport(batchReport.getID());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Hent en batchrapport
     * @param batchReportID
     * @return
     */
    public BatchReport getBatchReport(int batchReportID) {
        try {
            ResultSet rs = this.DBC.getBatchReport(batchReportID);
            int id = rs.getInt(1);
            String name = rs.getString(2);
            GregorianCalendar batchStartTime =  stringToDate(rs.getString(4));
            GregorianCalendar batchEndTime =  stringToDate(rs.getString(5));
            Boolean success = rs.getBoolean(6);
            String statusMessage = rs.getString(7);
            GregorianCalendar timeRecieved =  stringToDate(rs.getString(8));
            BatchReportDetailSet[] batchReportDetailSets = getBatchReportDetailSets(id);
            return new BatchReport(id, name, timeRecieved, batchStartTime, batchEndTime, success, statusMessage, batchReportDetailSets);
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Hent et batchrapportdetaljesæt
     * @param batchReportDetailSetID
     * @return
     */
    public BatchReportDetailSet getBatchReportDetailSet(int batchReportDetailSetID) {
        try {
            ResultSet rs = this.DBC.getBatchReportDetailSet(batchReportDetailSetID);
            int id = rs.getInt(1);
            String detailSetName = rs.getString(3);
            int totalUpdates = rs.getInt(4);
            int totalCreates = rs.getInt(5);
            int totalDeletes = rs.getInt(6);
            int totalErrors = rs.getInt(7);
            int totalSkips = rs.getInt(8);
            return new BatchReportDetailSet(id, detailSetName, totalUpdates, totalCreates, totalDeletes, totalErrors, totalSkips);
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //</editor-fold>

    //<editor-fold desc="Andet">

    /**
     * Hent alle batchrapportintervaller
     * @return
     */
    public BatchReportInterval[] getBatchReportIntervals() {
        ArrayList<BatchReportInterval> al = new ArrayList<BatchReportInterval>();
        try {
            ResultSet rs = this.DBC.getBatchReportIntervals();
            while(rs.next()) {
                al.add(new BatchReportInterval(rs.getInt(1), rs.getString(2)));
            }
            BatchReportInterval[] a = new BatchReportInterval[al.size()];
            for(int i = 0;i < a.length;i++) {
                a[i] = al.get(i);
            }
            return a;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //</editor-fold>
}
